using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace MinimizeEngine.Managers
{
    public class MEInputManager : GameComponent
    {
        #region Fields

        public KeyboardState CurrentKeyboardState;
        public GamePadState CurrentGamePadState;
        public MouseState CurrentMouseState;

        public KeyboardState LastKeyboardState;
        public GamePadState LastGamePadState;
        public MouseState LastMouseState;

        private Point mLastMouseLocation;

        private Vector2 mMouseMoved;

        #endregion

        #region Properties

        public Vector2 MouseMoved
        {
            get { return mMouseMoved; }
        }

        #endregion        

        #region Initialization

        public MEInputManager(Game game) : base(game)
        {
            Enabled = true;

            LastKeyboardState = CurrentKeyboardState;
            LastGamePadState = CurrentGamePadState;
            LastMouseState = CurrentMouseState;

            CurrentKeyboardState = Keyboard.GetState();
            CurrentGamePadState = GamePad.GetState(PlayerIndex.One);
            CurrentMouseState = Mouse.GetState();

            mMouseMoved = new Vector2(LastMouseState.X - CurrentMouseState.X, LastMouseState.Y - CurrentMouseState.Y);
            mLastMouseLocation = new Point(CurrentMouseState.X, CurrentMouseState.Y);
        }
 
        #endregion
        
        #region Update

        /// <summary>
        /// Reads the latest state of the Keyboard and Gamepad.
        /// </summary>
        public void Update()
        {
            #if !XBOX360
            if(!MEEngineManager.Console.DrawConsole)
            {
                LastKeyboardState = CurrentKeyboardState;
                LastGamePadState = CurrentGamePadState;
                LastMouseState = CurrentMouseState;

                CurrentKeyboardState = Keyboard.GetState();
                CurrentGamePadState = GamePad.GetState(PlayerIndex.One);
                CurrentMouseState = Mouse.GetState();

                mMouseMoved = new Vector2(LastMouseState.X - CurrentMouseState.X, LastMouseState.Y - CurrentMouseState.Y);
                mLastMouseLocation = new Point(CurrentMouseState.X, CurrentMouseState.Y);
            }
            #endif

            #if XBOX360
            LastKeyboardState = CurrentKeyboardState;
            LastGamePadState = CurrentGamePadState;
            LastMouseState = CurrentMouseState;

            CurrentKeyboardState = Keyboard.GetState();
            CurrentGamePadState = GamePad.GetState(PlayerIndex.One);
            CurrentMouseState = Mouse.GetState();

            mMouseMoved = new Vector2(LastMouseState.X - CurrentMouseState.X, LastMouseState.Y - CurrentMouseState.Y);
            mLastMouseLocation = new Point(CurrentMouseState.X, CurrentMouseState.Y);
            #endif

        }

        #endregion

        #region Key/Button/Mouse Checks

        /// <summary>
        /// Check to see if a new key was pressed during the current Update.
        /// controllingPlayer specifies which player is checked for Input.
        /// playerIndex specifies which player pressed it.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsNewKeyPress(Keys key)
        {
                return (CurrentKeyboardState.IsKeyDown(key) &&
                    LastKeyboardState.IsKeyUp(key));
        }

        /// <summary>
        /// Check to see if a new button was pressed during the current Update.
        /// controllingPlayer specifies which player is checked for Input.
        /// playerIndex specifies which player pressed it.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsNewButtonPress(Buttons button)
        {
                return (CurrentGamePadState.IsButtonDown(button) &&
                    LastGamePadState.IsButtonUp(button));
        }

        public bool IsCursorWithinWindowBounds()
        {
            int width = MEEngineManager.Game.Window.ClientBounds.Width;
            int height = MEEngineManager.Game.Window.ClientBounds.Height;

            if(CurrentMouseState.X > 0 && CurrentMouseState.X < width &&
                CurrentMouseState.Y > 0 && CurrentMouseState.Y < height)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        #endregion

        #region High Level Methods

        /// <summary>
        /// Checks to see if a Menu Option has been Selected
        /// A Menu Option can be selected via the following:
        ///  - Enter on Keyboard
        ///  - A Button on GamePad
        /// </summary>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsMenuOptionSelected()
        {
            return IsNewKeyPress(Keys.Enter) ||
                IsNewButtonPress(Buttons.A);
        }

        /// <summary>
        /// Checks to see if a Menu Option has been Canceled
        /// A Menu Option can be canceled via the following:
        ///  - Escape on Keyboard
        ///  - B Button on GamePad
        /// </summary>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsMenuOptionCancel()
        {
            return IsNewKeyPress(Keys.Escape) ||
                IsNewButtonPress(Buttons.B);
        }

        /// <summary>
        /// Check to see if we are Moving Up the Menu
        /// A Menu Up command can be detected via the following:
        ///  - Up Arrow on Keyboard
        ///  - DPad Up on GamePad
        ///  - Left Thumb Stick Up on GamePad
        /// </summary>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsMenuOptionUp()
        {
            return IsNewKeyPress(Keys.Up) ||
                IsNewButtonPress(Buttons.DPadUp) ||
                IsNewButtonPress(Buttons.LeftThumbstickUp);
        }

        /// <summary>
        /// Check to see if we are Moving Down the Menu
        /// A Menu Down command can be detected via the following:
        ///  - Up Arrow on Keyboard
        ///  - DPad Up on GamePad
        ///  - Left Thumb Stick Up on GamePad
        /// </summary>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsMenuOptionDown()
        {
            return IsNewKeyPress(Keys.Down)||
                IsNewButtonPress(Buttons.DPadDown) ||
                IsNewButtonPress(Buttons.LeftThumbstickDown);
        }

        /// <summary>
        /// Checks to see if the Game has been Paused
        /// A Pause command can be detected via the following:
        ///  - Escape on Keyboard
        ///  - Start on GamePad
        /// </summary>
        /// <param name="controllingPlayer"></param>
        /// <param name="playerIndex"></param>
        /// <returns></returns>
        public bool IsPause()
        {
            return IsNewKeyPress(Keys.Escape) ||
                IsNewButtonPress(Buttons.Start);
        }

        #endregion
    }
}
